package org.bigdata.framework.admin.web.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 文件下载工具类
 * 
 * @author hexin
 * @version 2.0
 * @date 2016.12.14
 */
public class FileDownloadUtil {

	private FileDownloadUtil() {}

	/**
	 * 文件下载
	 * 
	 * <pre>
	 * download("/home/test.txt", null, request, response)      ===> test.txt
	 * download("/home/test.txt", "", request, response)        ===> test.txt
	 * download("/home/test.txt", "new", request, response)     ===> new.txt
	 * download("/home/test.txt", "new.csv", request, response) ===> new.csv
	 * </pre>
	 * 
	 * @param filepath 文件本地绝对路径
	 * @param downloadName 客户端显示的文件名。如果不包含扩展文件名则自动追加本地文件的扩展文件名，如果包含则不修改
	 */
	public static void download(String filepath, String downloadName, HttpServletRequest request, HttpServletResponse response)
			throws IOException {
		download(new File(filepath), downloadName, request, response);
	}

	/**
	 * 文件下载
	 * 
	 * <pre>
	 * download(new File("/home/test.txt"), null, request, response)      ===> test.txt
	 * download(new File("/home/test.txt"), "", request, response)        ===> test.txt
	 * download(new File("/home/test.txt"), "new", request, response)     ===> new.txt
	 * download(new File("/home/test.txt"), "new.csv", request, response) ===> new.csv
	 * </pre>
	 * 
	 * @param filepath 文件本地绝对路径
	 * @param downloadName 客户端显示的文件名。如果不包含扩展文件名则自动追加本地文件的扩展文件名，如果包含则不修改
	 */
	public static void download(File file, String downloadName, HttpServletRequest request, HttpServletResponse response)
			throws IOException {
		// 文件合法性检验
		if (!file.exists()) {
			throw new FileNotFoundException(file.getAbsolutePath());
		}
		if (file.isDirectory()) {
			throw new IOException("Need a file instead of a directory! " + file.getAbsolutePath());
		}

		// 文件名处理
		String filename = file.getName(), dname = downloadName == null ? downloadName : downloadName.trim();
		if (dname == null || dname.isEmpty()) {
			dname = filename;
		} else {
			if (dname.lastIndexOf('.') == -1) {
				int index = filename.lastIndexOf('.');
				if (index != -1) {
					dname += filename.substring(index);
				}
			}
		}

		// 文件下载
		download(new FileInputStream(file), dname, request, response);
	}

	/**
	 * 文件流下载
	 * 
	 * @param downloadName 客户端显示的文件名，不能为空。如：file.txt
	 */
	public static void download(InputStream in, String downloadName, HttpServletRequest request, HttpServletResponse response)
			throws IOException {
		try {
			boolean isIE = request.getHeader("User-Agent").toUpperCase().contains("MSIE");
			downloadName = isIE ? URLEncoder.encode(downloadName, "UTF-8") : new String(downloadName.getBytes(), "ISO-8859-1");
			// name.getBytes("UTF-8")处理safari的乱码问题
			// filename = new String(isIE ? filename.getBytes() : filename.getBytes("UTF-8"), "ISO-8859-1");
		} catch (UnsupportedEncodingException e) {}

		// 设置输出的格式
		response.reset();
		response.setContentType("application/octet-stream");
		response.addHeader("Content-Disposition", "attachment; filename=\"" + downloadName + "\"");
		response.addHeader("Content-Length", "" + in.available());

		write(in, response.getOutputStream());
	}

	private static void write(InputStream in, OutputStream out)
			throws IOException {
		try {
			int len = 0;
			byte[] b = new byte[1024];
			// 循环取出流中的数据
			while ((len = in.read(b)) > 0) {
				out.write(b, 0, len);
			}
		} catch (IOException e) {
			throw e;
		} finally {
			if (out != null) {
				try {
					out.close();
				} catch (IOException e) {}
			}
			if (in != null) {
				try {
					in.close();
				} catch (IOException e) {}
			}
		}
	}

}
